package jumavidesktop.Manejadores.Implementaciones;

import Pruebas.Manolo.FreqSortMultiSet;
import Pruebas.Manolo.LevenshteinDistance;
import dtkanpr.ANPREngine;
import dtkanpr.Plate;
import dtkanpr.PlateCollection;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import javax.imageio.ImageIO;
import jumavidesktop.Manejadores.Intefaces.IMCamara;
import jumavidesktop.Manejadores.Intefaces.INotificadoMatricula;
import jumavidesktop.Otros.DetectMotion.PuenteCamara;
import jumavidesktop.Persistencia.entidades.Camara;
import jumavidesktop.Persistencia.entidades.Configanpr;
import jumavidesktop.Persistencia.entidades.EnumeracionesEntidades.TipoMovimiento;
import jumavidesktop.Persistencia.entidades.Matricula;
import jumavidesktop.Persistencia.entidades.Movimientos;

/**
 *
 * @author vimso
 * 
 * 
 * 
 */public class MCamara implements IMCamara, Runnable{
         ANPREngine anprEngine;
    List<INotificadoMatricula> detectoresMatricula;             
    LinkedList<Image> cola;
    Camara camara;
    PuenteCamara puenteCamara;
    Configanpr anpr;
    Movimientos movimiento;
    
    public MCamara(Camara camara) {
        this.camara = camara;
        cola = new LinkedList<>();
        this.puenteCamara = new PuenteCamara(camara.getConfigdetectionmotion(), cola);
        this.anpr = camara.getConfiganpr();
        this.detectoresMatricula = new ArrayList<>();       
        iniciarAnprEngine();
        movimiento = new Movimientos();
    }
    
    public void iniciarAnprEngine(){
        //System.load("D:/Archivos de Programa/DTK Software/DTK ANPR SDK/Bin/DTKANPR.dll");
        System.load("D:/Archivos de Programa/DTK Software/DTK ANPR SDK/Bin/DTKANPR.dll");
        //System.load("D:/Archivos de Programa/DTK Software/DTK ANPR SDK/Bin/DTKANPR.dll");
        anprEngine = new ANPREngine();
        //anprEngine.AddLicenseKey("7D667396DFFF9F595FBB9150AE2A0CB32BBB14BDA36029F54DC94B14904A4BB4C575E679FE2949585A6E638E9765E7E05F8A6F36B6FC8B7632E43326B95297F7390364527AEE9F487B4DB928D13C5AF8B2BC22584E");
        anprEngine.Init(false);
        //anprEngine.AddLicenseKey(null);
        anprEngine.SetMaxCharHeight(anpr.getSizeMax());
        anprEngine.SetMinimumCharHeight(anpr.getSizeMin()); 
        anprEngine.SetCountryCode("ES");
    }
    
    public void agregarDetectores(List<INotificadoMatricula> detectoresMatricula){
        for (INotificadoMatricula iDetectorMatricula : detectoresMatricula) {
            this.attach(iDetectorMatricula);
        }
    }
    public void arrancarCamara(List<INotificadoMatricula> detectoresMatricula) {
        this.puenteCamara.arrancaCamara();      
    }
    
    @Override
    public void pararCamara() {
        throw new UnsupportedOperationException("Not supported yet.");
    }

    @Override
    public void attach(INotificadoMatricula observador) {
        this.detectoresMatricula.add(observador);
    }

    @Override
    public void dettach(INotificadoMatricula observador) {
        this.detectoresMatricula.remove(observador);
    }
 
    @Override
    public void notificarObservadores(Movimientos mv) {
        for (INotificadoMatricula item : detectoresMatricula) {
            item.detectadaMatricula(mv);
        }        
    }
    
    public Camara getCamara() {
        return camara;
    }
    
    private Movimientos crearMov(String foto, String mov, String matricula){
        Movimientos aux = new Movimientos();
        
        //creo matricula
        Matricula mat = new Matricula();
        
        //creo y añado fecha
        SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy  kk:mm");
        Date fecha = this.StringToDate(df.format(new Date()));

        //añado datos a matricula.
        mat.setFechaAlta(fecha);
        mat.setMatricula(matricula);
        
        //meto datos en el movmimiento.
        aux.setCamaraid(camara);
        aux.setFechaYHora(fecha);
        aux.setFoto(foto);
        aux.setMatricula(mat);
        if(mov==TipoMovimiento.ENTRADA.toString())
            aux.setMovimiento(TipoMovimiento.ENTRADA);
        else
            aux.setMovimiento(TipoMovimiento.SALIDA);
        
        return aux;
    }
    
    public PuenteCamara getPanelVideo(){
        return puenteCamara;
    }

    public void setCamara(Camara camara) {
        this.camara = camara;
    }
   
    //Devuele un java.util.Date desde un String en formato dd-MM-yyyy
    //@param La fecha a convertir a formato date
    //@return Retorna la fecha en formato Date
    private Date StringToDate(String fecha) {
        SimpleDateFormat formatoDelTexto = new SimpleDateFormat("dd-MM-yyyy");
        Date fechaEnviar = null;
        System.out.println("esto vale fecha "+fecha);
        try {
            fechaEnviar = formatoDelTexto.parse(fecha);
            System.out.println("Esto vale total "+fechaEnviar);
            return fechaEnviar;
        } catch (ParseException ex) {
            ex.printStackTrace();
            return null;
        }
    }

    @Override
    public void reconocerImagen(Image imagen) {
        this.crearFicheroJPG(imagen, "c:\\algopla\\foto"+System.currentTimeMillis()+".jpg");
        //cola.add(imagen);
        //Aqui ya llamaría al anpr  y cuando se viese deberíamos llamara a this.notificarObservadores();        
    }
    
    public static void crearFicheroJPG(Image imagen, String RutaFichero){
        try {
            
           int           w = imagen.getWidth(null);
           int           h = imagen.getHeight(null);
           BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
           Graphics2D    g2 = bi.createGraphics();
           g2.drawImage(imagen, 0, 0, null);
           g2.dispose();
           String fileType = RutaFichero.substring(RutaFichero.indexOf('.')+1);
           ImageIO.write(bi, fileType, new File(RutaFichero));
        } catch (IOException ex) {
            
        }
    }

    @Override
    public void run() {
        PlateCollection plates;
        FreqSortMultiSet<String> set = FreqSortMultiSet.create(false);
        FreqSortMultiSet<String> aux;
        boolean centinela = false;
        puenteCamara.arrancaCamara();
        puenteCamara.repintar();
        while(true){
         while (!cola.isEmpty()) {  
            if (!cola.isEmpty()) {
                    try {
                        Image img = cola.get(0);
                        cola.remove(0);
                        plates = anprEngine.ReadFromImage((BufferedImage) img, 0);
                        if (plates != null) {
                            long count = plates.getCount();
                            if (count > 0) {
                                Plate plate = plates.getPlate(0);
                                if (plate != null && plate.text.length()>=7 && plate.text.length()<=8){
                                    String plateText = plate.text;
//                                    System.out.println("License plate text: "
//                                            + plateText);
                                    set.add(plateText);
                                    //System.out.println(plateText);
                                    if(set.count(set.primero())>=3) {
                                        if(centinela==false){
                                            centinela=true;
                                            String ruta = "C:\\"+plateText+".jpeg";
                                            this.crearFicheroJPG(img, "C:\\"+plateText+".jpeg");
                                            movimiento = this.crearMov(ruta, camara.getTipoCamara().toString(), plateText);
                                            this.notificarObservadores(movimiento);
                                            //System.out.println("Actualizo matriculas es: "+ set.primero());
//                                            System.out.println("\n¡¡ Abrir barrera¡¡\n\n\n");
                                        }
                                    }
                                    if(LevenshteinDistance.computeLevenshteinDistance(plateText, set.primero())>3){
                                            centinela=false;
                                            set.clear();
//                                            System.out.println("\n\nMATRICULA NUEVA TRONCO____________");
                                                
                                            set.add(plateText);
                                    }
                                   // System.out.println("Este es el primero:  "+set.descendingMultiset().firstEntry().toString());
                                }
                            }                           
                        }
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                
            }
            
        }
    }
    }
}
